package com.dj.ms.support.plus;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.dj.common.exception.CentralException;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.util.Arrays;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

/**
 * <br>
 * <p>
 *     ORM映射代码生成器
 * </p>
 *
 * <br>
 * @author ZJG
 * @version 1.0
 * @date 2021/9/29 上午9:54
 */
@Slf4j
@Component
public final class MapperGenerator {

    private static ThreadLocal<AtomicInteger> step = new ThreadLocal<>();

    private GeneratorConfig.Processor generatorConfigProcessor;
    private static PlusDataSourceConfig.Processor plusDataSourceConfig;

    static {
        plusDataSourceConfig = new PlusDataSourceConfig.Processor();
        step.set(new AtomicInteger(0));
    }

    private MapperGenerator() {
        this.generatorConfigProcessor = new GeneratorConfig.Processor();
    }

    public static MapperGenerator init(Consumer<PlusDataSourceConfig.Processor> consumer) {
        consumer.accept(plusDataSourceConfig);
        step.get().set(1);
        return new MapperGenerator();
    }

    public MapperGenerator generatorConfig(Consumer<GeneratorConfig.Processor> consumer) throws CentralException {
        consumer.accept(this.generatorConfigProcessor);
        if (Objects.isNull(step.get()) || step.get().get() != 1) {
            throw new CentralException("500", "MapperGenerator未进行初始化");
        }
        step.get().set(2);
        return this;
    }

    public void exec() throws CentralException {
        if (Objects.isNull(step.get()) || step.get().get() != 2) {
            throw new CentralException("500", "MapperGenerator未完成配置");
        }
        doExecute();
    }

    private void doExecute() {
        PlusDataSourceConfig dataSourceConfig = MapperGenerator.plusDataSourceConfig.process();
        GeneratorConfig generatorConfig = generatorConfigProcessor.process();
        FastAutoGenerator.create(dataSourceConfig.getUrl(), dataSourceConfig.getUsername(), dataSourceConfig.getPassword())
                .globalConfig(builder -> {
                    builder.disableOpenDir()
                            .fileOverride()
                            .author(generatorConfig.getAuthor())
                            .outputDir(generatorConfig.getAdsDirectory())
                            .commentDate("yyyy-MM-dd HH:mm:ss")
                            .enableSwagger();
                })
                .packageConfig(builder -> {
                    builder.parent(generatorConfig.getParentPkg())
                            .entity("dao.entity")
                            .mapper("dao.mapper")
                            .xml("dao.mapper.xml");

                    if (StrUtil.isNotBlank(generatorConfig.getDaoSerPkg())) {
                        builder.service(generatorConfig.getDaoSerPkg())
                                .serviceImpl(generatorConfig.getDaoSerPkg() + ".impl");
                    }
                })
                .strategyConfig(builder -> {
                    builder.entityBuilder().formatFileName("%sBean")
                                            .naming(NamingStrategy.underline_to_camel)
                                            .columnNaming(NamingStrategy.underline_to_camel)
                                            .enableChainModel()
                                            .enableLombok()
                            .mapperBuilder().formatMapperFileName("%sMapper")
                                            .formatXmlFileName("%sMapper")
                            .controllerBuilder().formatFileName("%sController")
                                                .enableRestStyle()
                            .serviceBuilder().formatServiceFileName("%sService")
                                            .formatServiceImplFileName("%sServiceImpl");
                    if (Objects.nonNull(generatorConfig.getSuperEntityCls())) {
                        builder.entityBuilder().superClass(generatorConfig.getSuperEntityCls());
                    }
                    if (Objects.nonNull(generatorConfig.getSuperControllerCls())) {
                        builder.controllerBuilder().superClass(generatorConfig.getSuperControllerCls());
                    }
                    if (Objects.nonNull(generatorConfig.getSuperServiceCls())) {
                        builder.serviceBuilder().superServiceClass(generatorConfig.getSuperServiceCls());
                    }
                    if (Objects.nonNull(generatorConfig.getSuperServiceImplCls())) {
                        builder.serviceBuilder().superServiceImplClass(generatorConfig.getSuperServiceImplCls());
                    }
                    if (!Arrays.isNullOrContainsNull(generatorConfig.getTbMatch())) {
                        builder.disableSqlFilter()
                                .addInclude(generatorConfig.getTbMatch());
                    }
                    if (!Arrays.isNullOrContainsNull(generatorConfig.getTbPrefix())) {
                        builder.addTablePrefix(generatorConfig.getTbPrefix());
                    }
                    if (!Arrays.isNullOrContainsNull(generatorConfig.getTbSuffix())) {
                        builder.addTableSuffix(generatorConfig.getTbSuffix());
                    }
                })
                .execute();
        log.info("Generator exec finished.");
    }

}
